#!pip install plotly
#!pip install folium
#!pip install cairosvg
#!pip install pygal_maps_fr
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
#import pygal_maps_fr
import json
import folium
import plotly.express as px
geo = json.load(open("departements.geojson"))
#geo = json.load(open("D:\Programme Python\Projet Python\departements.geojson"))
geoarr = json.load(open("arrondissements.geojson"))
df = pd.read_csv('valeursfoncieres-2020.txt',sep='|',decimal = ',') #creation de la DataFrame
df2019 = pd.read_csv('valeursfoncieres-2019.txt',sep='|',decimal = ',')
# temps d'attente assez élévé mais normal on charge plus de 8 millions de lignes de données
C:\Users\Azizm\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (14,18,23,24,26,28,41) have mixed types.Specify dtype option on import or set low_memory=False. has_raised = await self.run_ast_nodes(code_ast.body, cell_name, C:\Users\Azizm\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (18,23,24,26,28,41) have mixed types.Specify dtype option on import or set low_memory=False. has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
Ce bloc sert à nettoyer la dataframe et à modifier les types de certaines valeurs pour faciliter l'utilisation
df.drop(df.iloc[:, :7], inplace = True, axis = 1)
df2019.drop(df.iloc[:, :7], inplace = True, axis = 1)
#on remarque que les 7 premières colonnes ne servent à rien il n'y a pas de données.
df.columns = [c.replace('/', '_') for c in df.columns]
df2019.columns = [c.replace('/', '_') for c in df.columns]
#on remplace les '/' pour pouvoir appeler la colonne plus facilement.
df.columns = [c.replace(' ', '_') for c in df.columns]
df2019.columns = [c.replace(' ', '_') for c in df.columns]
#pareil avec les espaces
#Les deux lignes de code du dessous servent à convertir la colonne valeur fonciere en float mais cette etape a été faite dans l'importation
#df['Valeur_fonciere'] = df['Valeur_fonciere'].replace({',' : '.'},regex=True) #on remplace les ',' dans la colonne valeur fonciere pour pouvoir la convertir en float
#df.Valeur_fonciere = df.Valeur_fonciere.apply(lambda x :float(x)) #conversion en float
df.Code_departement = df['Code_departement'].apply(lambda x :str(x))
df2019.Code_departement = df['Code_departement'].apply(lambda x :str(x))
#conversion de la colonne en str car quand on fait la jointure pour les cartes il faut avoir des str
df['Code_departement'] = df['Code_departement'].replace({'1' : '01','2' : '02','3' : '03','4' : '04','5' : '05','6': '06','7' : '07' , '8' : '08' , '9' : '09'})
df2019['Code_departement'] = df['Code_departement'].replace({'1' : '01','2' : '02','3' : '03','4' : '04','5' : '05','6': '06','7' : '07' , '8' : '08' , '9' : '09'})
#on remplace les 9 premiers départements en mettant un 0 devant car dans les données geojson il y a un 0 devant
df['Code_type_local'] = df['Code_type_local'].replace({1 : 'Maison',2 : 'Appartement',3 : 'Dépendance_isolée',4 : 'Local_industriel_et_commercial'})
df2019['Code_type_local'] = df['Code_type_local'].replace({1 : 'Maison',2 : 'Appartement',3 : 'Dépendance_isolée',4 : 'Local_industriel_et_commercial'})
#On change les chiffres de la colonne Code_type_local par des données plus concrètes
Cette première cellule sert à créer une datafram groupé par rapport au code département et en faisant la somme sur les différentes colonnes.
df_departement_somme = df.groupby(['Code_departement']).sum().reset_index()
df_departement_somme["Surface_terrain"] = df_departement_somme["Surface_terrain"]/100000 #on divise par une puissance de dix pour rendre les graphiques plus lisible
df_departement_somme["Surface_reelle_bati"] = df_departement_somme["Surface_reelle_bati"]/10000
df_departement_somme["Valeur_fonciere"] = df_departement_somme["Valeur_fonciere"]/1000
df2019_departement_somme = df2019.groupby(['Code_departement']).sum().reset_index()
df2019_departement_somme["Surface_terrain"] = df2019_departement_somme["Surface_terrain"]/1000 #on divise par une puissance de dix pour rendre les graphiques plus lisible
df2019_departement_somme["Surface_reelle_bati"] = df2019_departement_somme["Surface_reelle_bati"]/1000
df2019_departement_somme["Valeur_fonciere"] = df2019_departement_somme["Valeur_fonciere"]
Dans cette section nous allons confronter différentes carte de France suivant une certaine valeur sur deux années consécutives 2019 et 2020.
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df_departement_somme, columns = ["Code_departement", "Valeur_fonciere"],
fill_color = "Spectral"
)
france
C:\Users\Azizm\anaconda3\lib\site-packages\folium\folium.py:409: FutureWarning: The choropleth method has been deprecated. Instead use the new Choropleth class, which has the same arguments. See the example notebook 'GeoJSON_and_choropleth' for how to do this. warnings.warn(
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df2019_departement_somme, columns = ["Code_departement", "Valeur_fonciere"],
fill_color = "Spectral"
)
france
On remarque tout d'abord qu'en 2020 la somme des valeurs foncières d'un département est plus ou moins homogène partout excepté dans le 95 où elle est beaucoup plus importante. Tandis que sur la carte de 2019 il est exctaement semblable parout nous supposons donc que il y a eu une erreur lors de la lecture de la dataframe.
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df_departement_somme, columns = ["Code_departement", "Surface_terrain"],
fill_color = "Spectral"
)
france
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df2019_departement_somme, columns = ["Code_departement", "Surface_terrain"],
fill_color = "Spectral"
)
france
On remarque que la carte est globalement plus clair en 2020 comparé à celle de 2019.
Et c'est vers l'ouest qu'il y le plus de surface terrain.
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df_departement_somme, columns = ["Code_departement", "No_plan"],
fill_color = "Spectral"
)
france
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df_departement_somme, columns = ["Code_departement", "Surface_reelle_bati"],
fill_color = "Spectral"
)
france
Le nombre de plan a gloabalement diminué mais il reste le plus haut dans l'ouest au niveau de la bretagne.
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df_departement_somme, columns = ["Code_departement", "Nombre_de_lots"],
fill_color = "Spectral"
)
france
france = folium.Map(location = [48.856578, 2.351828], zoom_start = 5)
france.choropleth(geo, key_on = "feature.properties.code",
data = df2019_departement_somme, columns = ["Code_departement", "Nombre_de_lots"],
fill_color = "Spectral"
)
france
Le nombre de lots a diminué glabalement et il est le plus haut en ile-de-france.
df_paris = df.loc[df['Code_departement'] == "75" ].reset_index()
df_paris.Code_postal = df_paris.Code_postal.apply(lambda x : str(x)[3:5])
df_paris.Code_postal = df_paris.Code_postal.apply(lambda x : int(x) if x != '' else np.nan)
paris = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
paris.choropleth(geoarr, key_on = "feature.properties.c_ar",
data = df_paris, columns = ["Code_postal", "Surface_reelle_bati"],
fill_color = "Spectral")
paris
paris = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
paris.choropleth(geoarr, key_on = "feature.properties.c_ar",
data = df_paris, columns = ["Code_postal", "No_plan"],
fill_color = "Spectral")
paris
df_un_departement = df.loc[df['Code_departement'] == "75" ].reset_index()
# color pallette
cnf = '#393e46' # confirmed - grey
dth = '#ff2e63' # death - red
rec = '#21bf73' # recovered - cyan
act = '#fe9801' # active case - yellow
df_departement_10_premier = df_departement_somme.sort_values(['Valeur_fonciere'],ascending = False)[0:19]
#création d'une datafram groupé par code département et trié par valeur fonciere et on gare les 20 premier
plt.figure(figsize=(10,10))
sns.barplot(y="Code_departement",x="Valeur_fonciere",data=df_departement_10_premier)
<AxesSubplot:xlabel='Valeur_fonciere', ylabel='Code_departement'>
df2019_departement_10_premier = df2019_departement_somme.sort_values(['Surface_terrain'],ascending = False)[0:19]
#création d'une datafram groupé par code département et trié par valeur fonciere et on gare les 20 premier
plt.figure(figsize=(10,10))
sns.barplot(y="Code_departement",x="Surface_terrain",data=df2019_departement_10_premier)
<AxesSubplot:xlabel='Surface_terrain', ylabel='Code_departement'>
df_departement_10_premier = df_departement_somme.sort_values(['Surface_terrain'],ascending = False)[0:19]
#création d'une datafram groupé par code département et trié par valeur fonciere et on gare les 20 premier
plt.figure(figsize=(10,10))
sns.barplot(y="Code_departement",x="Surface_terrain",data=df_departement_10_premier)
<AxesSubplot:xlabel='Surface_terrain', ylabel='Code_departement'>
df_departement_10_premier = df_departement_somme.sort_values(['Nombre_pieces_principales'],ascending = False)[0:19]
#création d'une datafram groupé par code département et trié par valeur fonciere et on gare les 20 premier
plt.figure(figsize=(10,10))
sns.barplot(y="Code_departement",x="Nombre_pieces_principales",data=df_departement_10_premier)
<AxesSubplot:xlabel='Nombre_pieces_principales', ylabel='Code_departement'>
Ce sont les appartements qui ont la plus grande valeurs foncière en France. Cependant, ce sont les maisons qui demandent le plus de places
df_departement = df.groupby(['Code_type_local'])
df_departement.Valeur_fonciere.sum().plot.pie(y = "Valeur fonciere", figsize = (6,6))
<AxesSubplot:ylabel='Valeur_fonciere'>
df_departement = df.groupby(['Code_type_local'])
df_departement.Surface_terrain.sum().plot.pie(y = "Surface_terrain", figsize = (6,6))
<AxesSubplot:ylabel='Surface_terrain'>
df_departement = df.groupby(['Code_type_local'])
df_departement.Surface_reelle_bati.sum().plot.pie(y = "Surface_reelle_bati", figsize = (6,6))
<AxesSubplot:ylabel='Surface_reelle_bati'>
La valeur foncière, la surface des terrains vendus et la surface réelle bati restent globalement stable au cours du temps
temp = df.groupby('Date_mutation')['Valeur_fonciere'].sum().reset_index()
temp = temp.melt(id_vars="Date_mutation", value_vars=['Valeur_fonciere'],
var_name='Variable', value_name='Valeur_fonciere')
temp.head()
fig = px.area(temp, x="Date_mutation", y="Valeur_fonciere", color='Variable',
title='Valeur foncière en fonction du temps', color_discrete_sequence = [rec], height = 490)
fig.show()
temp = df.groupby('Date_mutation')['Surface_terrain'].sum().reset_index()
temp = temp.melt(id_vars="Date_mutation", value_vars=['Surface_terrain'],
var_name='Variable', value_name='Surface_terrain')
temp.head()
fig = px.area(temp, x="Date_mutation", y="Surface_terrain", color='Variable',
title='Surface terrain en fonction du temps', color_discrete_sequence = [dth], height = 490)
fig.show()
temp = df.groupby('Date_mutation')['Surface_reelle_bati'].sum().reset_index()
temp = temp.melt(id_vars="Date_mutation", value_vars=['Surface_reelle_bati'],
var_name='Variable', value_name='Surface_reelle_bati')
temp.head()
fig = px.area(temp, x="Date_mutation", y="Surface_reelle_bati", color='Variable',
title='Surface reelle bati en fonction du temps', color_discrete_sequence = [act], height = 490)
fig.show()
<ipython-input-26-da6d1d2e273f>:2: FutureWarning: This dataframe has a column name that matches the 'value_name' column name of the resultiing Dataframe. In the future this will raise an error, please set the 'value_name' parameter of DataFrame.melt to a unique name. temp = temp.melt(id_vars="Date_mutation", value_vars=['Valeur_fonciere'],
<ipython-input-26-da6d1d2e273f>:12: FutureWarning: This dataframe has a column name that matches the 'value_name' column name of the resultiing Dataframe. In the future this will raise an error, please set the 'value_name' parameter of DataFrame.melt to a unique name.
<ipython-input-26-da6d1d2e273f>:22: FutureWarning: This dataframe has a column name that matches the 'value_name' column name of the resultiing Dataframe. In the future this will raise an error, please set the 'value_name' parameter of DataFrame.melt to a unique name.
On remarque que la majorité de la valeur foncière de la France est concentré dans quelques départements. Notamment le 95, le 75 et le 92
temp = df.groupby('Date_mutation')['Valeur_fonciere'].sum().reset_index()
max(temp['Valeur_fonciere'])
fig = px.bar(df.sort_values('Valeur_fonciere', ascending=False).head(20000).sort_values('Valeur_fonciere', ascending=True),
x="Valeur_fonciere", y="Code_departement", title='Valeur foncière par département', text='Valeur_fonciere', orientation='h',
width=1000, height=1200, range_x = [0, max(temp['Valeur_fonciere'])+100000000000])
fig.update_traces(marker_color=rec, opacity=1, textposition='outside')
fig.show()
La surface réel bâti est relativement faible à Paris comparé à ça valeur foncière. Cela peut être expliqué par le faite qu'à Paris, il y a beaucoup d'appartement qui ont besoin de moins d'espace.
temp = df.groupby('Date_mutation')['Surface_reelle_bati'].sum().reset_index()
max(temp['Surface_reelle_bati'])
fig = px.bar(df.sort_values('Surface_reelle_bati', ascending=False).head(1000).sort_values('Valeur_fonciere', ascending=True),
x="Surface_reelle_bati", y="Code_departement", title='Surface réel bâti par département', text='Surface_reelle_bati', orientation='h',
width=1000, height=1500, range_x = [0, max(temp['Surface_reelle_bati'])+500000])
fig.update_traces(marker_color=act, opacity=1, textposition='outside')
fig.show()
temp = df.groupby('Date_mutation')['Surface_terrain'].sum().reset_index()
fig = px.bar(df.sort_values('Surface_terrain', ascending=False).head(1000).sort_values('Valeur_fonciere', ascending=True),
x="Surface_terrain", y="Code_departement", title='Surface terrain', text='Surface_terrain', orientation='h',
width=1000, height=1500, range_x = [0, max(temp['Surface_terrain'])+500000])
fig.update_traces(marker_color=dth, opacity=1, textposition='outside')
fig.show()
On remarque une corrélation entre la valeur foncière par mètre carré de terrain et la valeur foncière par nombre de pièce principal. Cela est dû au fait que plus la valeur foncière à une date donnée est élévée, plus il y a de chances que des biens chères ont été vendu, et donc plus il y a de chance que des biens à beaucoup de pièces principales ont vendu.
temp = df.groupby('Date_mutation').sum().reset_index()
#Nombre_pieces_principales
# adding two more columns
temp['Surface_terrain'] = temp['Surface_terrain'] / 1000 #On divise par 1000 pour être du même ordre de grandeur Nombre_pieces_principales
temp['Valeur foncière par 1000 mètre carré de terrain'] = round(temp['Valeur_fonciere']/temp['Surface_terrain'], 3)
temp['Valeur foncière par nombre de pièces principales'] = round(temp['Valeur_fonciere']/temp['Nombre_pieces_principales'], 3)
temp = temp.melt(id_vars='Date_mutation', value_vars=['Valeur foncière par 1000 mètre carré de terrain','Valeur foncière par nombre de pièces principales'],
var_name='Ratio', value_name='Valeur')
fig = px.line(temp, x="Date_mutation", y="Valeur", color='Ratio', log_y=True,
title='Evolution de la valeur foncière en fonction du temps', color_discrete_sequence=[dth,rec])
fig.show()
temp = df.groupby('Code_departement').sum().reset_index()
#Nombre_pieces_principales
# adding two more columns
temp['Surface_terrain'] = temp['Surface_terrain'] / 1000 #On divise par 1000 pour être du même ordre de grandeur Nombre_pieces_principales
temp['Valeur foncière par 1000 mètre carré de terrain'] = round(temp['Valeur_fonciere']/temp['Surface_terrain'], 3)
temp['Valeur foncière par nombre de pièces principales'] = round(temp['Valeur_fonciere']/temp['Nombre_pieces_principales'], 3)
temp = temp.melt(id_vars='Code_departement', value_vars=['Valeur foncière par 1000 mètre carré de terrain','Valeur foncière par nombre de pièces principales'],
var_name='Ratio', value_name='Valeur')
fig = px.line(temp, x="Code_departement", y="Valeur", color='Ratio', log_y=True,
title='Valeur foncière par département', color_discrete_sequence=[dth,rec])
fig.show()
On remarque une forte variation d'un jour à l'autre de la surface reelle bati par surface des terrains au cour du temps. Cela est lié au faite qu'il y a de fortes variations de la surface reelle bâti au cours du temps.
temp = df.groupby('Date_mutation').sum().reset_index()
temp1 = df.groupby('Date_mutation').count().reset_index()
#Nombre_pieces_principales
# adding two more columns
temp['Moyenne de la surface des terrains'] = round(temp['Surface_terrain']/temp1['Surface_terrain'], 3)
temp['Moyenne de la surface reelle bati'] = round(temp['Surface_reelle_bati']/temp1['Surface_reelle_bati'], 3)
temp['Surface reelle bati par surface des terrains'] = round(temp['Moyenne de la surface reelle bati']/temp['Moyenne de la surface des terrains'], 3)
#temp = temp.melt(id_vars='Date_mutation', value_vars=['Moyenne de la surface des terrains','Moyenne de la surface reelle bati','Surface reelle bati par surface des terrains'],
# var_name='Ratio', value_name='Valeur')
temp = temp.melt(id_vars='Date_mutation', value_vars=['Surface reelle bati par surface des terrains'],
var_name='Ratio', value_name='Valeur')
fig = px.line(temp, x="Date_mutation", y="Valeur", color='Ratio', log_y=False,
title='Surface reelle bati par surface des terrains en fonction du temps', color_discrete_sequence=[cnf])
fig.show()
Ce ratio permet connaître les départements qui optimise le mieux leur surface. Le fait que Paris et Lyon soient dans les trois premiers est cohérent. On remarque aussi une corrélation entre ce ratio et la valeur foncière par mètre carré. ( Deux graphiques au dessus ). Ainsi, pour chaque département, la densité de logement est fonction croissante de la valeur foncière par mètre carré
temp = df.groupby('Code_departement').sum().reset_index()
temp1 = df.groupby('Code_departement').count().reset_index()
#Nombre_pieces_principales
# adding two more columns
temp['Moyenne de la surface des terrains'] = round(temp['Surface_terrain']/temp1['Surface_terrain'], 3)
temp['Moyenne de la surface reelle bati'] = round(temp['Surface_reelle_bati']/temp1['Surface_reelle_bati'], 3)
temp['Surface reelle bati par surface des terrains'] = round(temp['Moyenne de la surface reelle bati']/temp['Moyenne de la surface des terrains'], 3)
#temp = temp.melt(id_vars='Code_departement', value_vars=['Surface reelle bati par surface des terrains'],
# var_name='Ratio', value_name='Valeur')
#fig = px.line(temp, x="Code_departement", y="Valeur", color='Ratio', log_y=False,
#title='Surface reelle bati par surface des terrains en fonction du département', color_discrete_sequence=[cnf])
#fig.show()
#temp = df.groupby('Date_mutation')['Valeur_fonciere'].sum().reset_index()
temp2 = temp['Surface reelle bati par surface des terrains']
fig = px.bar(temp.sort_values('Surface reelle bati par surface des terrains', ascending=False).head(20).sort_values('Surface reelle bati par surface des terrains', ascending=True),
x="Surface reelle bati par surface des terrains", y="Code_departement", title='Surface reelle bati par surface des terrains en fonction du département', text='Surface reelle bati par surface des terrains', orientation='h',
width=900, height=900, range_x = [0, max(temp['Surface reelle bati par surface des terrains'])+0.03])
fig.update_traces(marker_color=cnf, opacity=1, textposition='outside')
fig.show()
On remarque que la surface des lots 2 et 3 sont très faible devant celle des lots 1 et 4.
temp = df.groupby('Date_mutation')['Surface_Carrez_du_1er_lot','Surface_Carrez_du_2eme_lot','Surface_Carrez_du_3eme_lot','Surface_Carrez_du_4eme_lot'].sum().reset_index()
temp = temp.melt(id_vars="Date_mutation", value_vars=['Surface_Carrez_du_1er_lot','Surface_Carrez_du_2eme_lot','Surface_Carrez_du_3eme_lot','Surface_Carrez_du_4eme_lot'],
var_name='Variable', value_name='Surface_terrain')
temp.head()
fig = px.area(temp, x="Date_mutation", y="Surface_terrain", color='Variable',
title='Surface terrain des premiers lots en fonction du temps', color_discrete_sequence = [dth,cnf,rec,act], log_y = True)
fig.show()
<ipython-input-34-5dec2e50931a>:1: FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead.